package com.yochi.pictureseditor.effects.effectsimpl;

import com.yochi.pictureseditor.effects.EffectParametrized;
import com.yochi.pictureseditor.exceptions.NullImageException;
import com.yochi.pictureseditor.images.Image;
import com.yochi.pictureseditor.images.ImageImpl;

public class EffectCustomRotation extends EffectParametrized {
	
	  //////////////////
	 // CONSTRUCTORS //
	//////////////////
	
	public EffectCustomRotation(Image img) {
		super(img, "Angle level", 0, 360);
		setPreParametrized(false);
	}
	
	public EffectCustomRotation(Image img, int param) {
		super(img, "Angle level", 0, 360);
		getParameter().setValue(param); 
		setPreParametrized(true);
	}
	
	  ////////////
	 // PUBLIC //
	////////////
	
	@Override
	public Image apply() throws NullImageException {
		if(getImage()==null) throw new NullImageException("load an image before applying effect");
		Image result = process();
		setResult(result);
		return result;
	}
	
	  ///////////////
	 // PROTECTED //
	///////////////

	@Override
	protected Image process() {
		double parameter = getParameter().getValue();
		if(parameter == 0 || parameter == 360) {
			return getImage();
		}
		
		// rescale parameter value (from degrees to radians)
		parameter = ((parameter)*2.0f*Math.PI)/360.0f;
		
		// compute new image size
		int newWidth = Double.valueOf(Math.round(
							Math.abs(getImage().getHauteur()*Math.sin(parameter)) 
							+ Math.abs(getImage().getLargeur()*Math.cos(parameter))
					)).intValue();
		int newHeight = Double.valueOf(Math.round(
							Math.abs(getImage().getHauteur()*Math.cos(parameter)) 
							+ Math.abs(getImage().getLargeur()*Math.sin(parameter))
					)).intValue();
		
		Image result = new ImageImpl(getImage().getProfondeur(), newWidth, newHeight);
		
		int centerLine = Math.round(getImage().getHauteur()/2);
		int centerColumn = Math.round(getImage().getLargeur()/2);

		int pixelValue;
		int wi, he;
		for(int p=0; p<result.getProfondeur(); p++) {
			for(int l=0; l<newWidth; l++) {
				for(int h=0; h<newHeight; h++) {
					
					// compute coordinate of pixel 
					he = Double.valueOf((l-(newWidth/2.0f))*Math.sin(parameter)+(h-(newHeight/2.0f))*Math.cos(parameter)).intValue() + centerLine;
					wi = Double.valueOf((l-(newWidth/2.0f))*Math.cos(parameter)-(h-(newHeight/2.0f))*Math.sin(parameter)).intValue() + centerColumn;
					
					if(wi>=0 && wi<getImage().getLargeur() && he>=0 && he<getImage().getHauteur()) {
						pixelValue = getImage().getPixel(p, wi, he);
					} else {
						pixelValue = 0;
					}
					
					// limit values
					if(pixelValue > 255) {
						pixelValue = 255;
					} else if(pixelValue < 0) {
						pixelValue = 0;
					}
					
					result.setPixel(p, l, h, (char) pixelValue);
				}  
			}   
		}
		return result;
	}
	
	@Override
	public String toString() {
		return "[EffectCustomRotation]";
	}

}
